package com.zyk.scaffold.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyk.scaffold.core.component.PasswordEncoderComponent;
import com.zyk.scaffold.common.enums.UserTypeEnum;
import com.zyk.scaffold.common.utils.AssertUtil;
import com.zyk.scaffold.common.utils.BeanCopyUtil;
import com.zyk.scaffold.oauth.rpc.OauthRpcService;
import com.zyk.scaffold.user.controller.user.UpdatePasswordRequ;
import com.zyk.scaffold.user.controller.user.UserInfosResp;
import com.zyk.scaffold.user.controller.user.UserNewRequ;
import com.zyk.scaffold.user.entity.User;
import com.zyk.scaffold.user.mapper.UserMapper;
import com.zyk.scaffold.user.service.UserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 用户-用户表 服务实现类
 * </p>
 *
 * @author zhouyk
 * @since 2021-12-06
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;

    @DubboReference
    private OauthRpcService oauthRpcService;

    @Autowired
    private PasswordEncoderComponent passwordEncoderComponent;

    @Override
    public User addUser(UserNewRequ userNewRequ, Long userId) {
        // if(!userNewRequ.getEmail().trim().toUpperCase().endsWith("QQ.COM")){
        //     AssertUtil.error("邮箱只支持QQ邮箱");
        // }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getAccount, userNewRequ.getEmail());
        List<User> users = userMapper.selectList(queryWrapper);
        if(users != null &&  users.size() > 0){
            return users.get(0);
        }
        User user = BeanCopyUtil.copyProperties(userNewRequ, User::new);
        user.setAccount(userNewRequ.getEmail());
        try {
            user.setPassword(passwordEncoderComponent.encode(user.getPassword(), null));
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
        user.setUpdateUser(userId);
        user.setCreateUser(userId);
        int insert = userMapper.insert(user);
        if(insert > 0){
            return user;
        }
        return null;
    }

    @Override
    public User getUserByAccount(String account) {
        if(StringUtils.isEmpty(account)){
            return null;
        }
        QueryWrapper<User>queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().apply("lower(account) = {0}", account)
                .eq(User::getDeleted, Boolean.FALSE)
                .eq(User::getEnable, Boolean.TRUE);
        List<User> list = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        if(list.size() == 1){
            return list.get(0);
        }else{
            for (User user : list) {
                if (account.equals(user.getAccount())){
                    return user;
                }
            }
            return null;
        }
    }

    @Override
    public List<User> getUsersByAccounts(List<String> accounts) {
        if(CollectionUtils.isEmpty(accounts)){
            return Collections.emptyList();
        }
        QueryWrapper<User>queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().apply("lower(account) in ({0})", StringUtils.join(accounts.stream().map(String::toLowerCase).map(String::trim).distinct().filter(StringUtils::isNotEmpty).toArray()))
                .eq(User::getDeleted, Boolean.FALSE)
                .eq(User::getEnable, Boolean.TRUE);
        List<User> list = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }
        return list;
    }

    @Override
    public List<UserInfosResp> listUserInfos(String name, String email) {
        if(email != null){
            email = email.trim();
        }
        if(name != null){
            name = name.trim();
        }
        QueryWrapper<User>queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .likeRight(StringUtils.isNotEmpty(email), User::getEmail, email)
                .likeRight(StringUtils.isNotEmpty(name), User::getName, name)
                .eq(User::getType, UserTypeEnum.USER_TYPE_BUSINESS.getCode())
                .eq(User::getDeleted, Boolean.FALSE)
                .eq(User::getEnable, Boolean.TRUE);
        List<User> list = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return Collections.emptyList();
        }
        return BeanCopyUtil.copyListProperties(list, UserInfosResp::new);
    }

    @Override
    public Boolean updatePassword(UpdatePasswordRequ userEnableRequ, Long userId) {
        if (!userEnableRequ.getNewPassword().equals(userEnableRequ.getConfirmPassword())) {
            AssertUtil.error("新密码不一致");
        }
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        try {
            updateWrapper.lambda()
                    .set(User::getPassword, passwordEncoderComponent.encode(userEnableRequ.getNewPassword(), null))
                    .eq(User::getId, userId);
        } catch (NoSuchAlgorithmException e) {
            AssertUtil.error("新密码加密失败");
        }
        boolean update = this.update(updateWrapper);
        if (update) {
            oauthRpcService.loginOutByUserId(userId);
        }
        return update;
    }

    @Override
    public User getUserByEmail(String email) {
        if(StringUtils.isEmpty(email)){
            return null;
        }
        QueryWrapper<User>queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().apply("lower(email) = {0}", email.toLowerCase())
                .eq(User::getDeleted, Boolean.FALSE)
                .eq(User::getEnable, Boolean.TRUE);
        List<User> list = this.list(queryWrapper);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        if(list.size() == 1){
            return list.get(0);
        }else{
            for (User user : list) {
                if (email.equals(user.getEmail())){
                    return user;
                }
            }
            return null;
        }
    }
}
